package com.winit.schedule.webc.support;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.winit.schedule.webc.annotation.ResponseType;
import com.winit.schedule.webc.exception.ScheduleWebcException;
import com.winit.schedule.webc.util.Constants;
import com.winit.schedule.webc.util.StringUtils;

public class ScheduleRequestInterceptor {

    private static final Logger     log              = LoggerFactory.getLogger(ScheduleRequestInterceptor.class);

    Map<String, ControllerDelegate> controllers      = new HashMap<String, ControllerDelegate>();

    ControllerParser                controllerParser = new DefaultControllerParser();

    public ScheduleRequestInterceptor(){
    }

    public void registerController(Object controller) {
        ControllerDelegate delegate = controllerParser.parse(controller);
        if (null != delegate) {
            if (controllers.containsKey(delegate.getNamespace())) {
                log.warn("Controller configuration error, the same as the two namespace controller : "
                         + delegate.getNamespace());
            } else {
                controllers.put(delegate.getNamespace(), delegate);
            }
        }

    }

    public Response interceptor(HttpServletRequest req, HttpServletResponse resp) throws IllegalArgumentException,
                                                                                 IllegalAccessException,
                                                                                 InvocationTargetException {
        String cmd = req.getParameter(Constants.CMD_KEY);
        if (!StringUtils.isBlank(cmd)) {
            String[] cmdArr = org.apache.commons.lang3.StringUtils.split(cmd, Constants.CMD_SEPARATOR);
            String namespace = "";
            String requestMapping = "";
            if (cmdArr.length == 1) {
                namespace = Constants.DEFAULT_NAMESPACE;
                requestMapping = cmdArr[0];
            } else {
                namespace = cmdArr[0];
                requestMapping = cmdArr[1];
            }

            if (!controllers.containsKey(namespace)) {
                log.warn("Corresponding namespace not found, namespace : " + namespace);
                throw new ScheduleWebcException("Corresponding namespace not found, namespace : " + namespace);
            } else {
                ControllerDelegate delegate = controllers.get(namespace);

                if (delegate.checkRequestMapping(namespace, requestMapping)) {
                    MethodMapping mapping = delegate.getMethodMapping(requestMapping);
                    try {
                        return mapping.invoke(req, resp);
                    } catch (Throwable e) {
                        String errorMsg = String.format("Request call failed, namespace : %s, requestMapping : %s", namespace, requestMapping);
                        log.error(errorMsg, e);
                        throw new ScheduleWebcException(errorMsg, e);
                    }
                    
                } else {
                    String errorMsg = String.format("Request call failed, namespace : %s, requestMapping : %s", namespace, requestMapping);
                    log.error(errorMsg);
                    throw new ScheduleWebcException(errorMsg);
                }
            }
        }

        return new RedirectResponse(ResponseType.REDIRECT, "");
    }

    public String getNamespace(HttpServletRequest req) {
        String cmd = req.getParameter(Constants.CMD_KEY);
        String namespace = null;
        if (!StringUtils.isBlank(cmd)) {
            String[] cmdArr = org.apache.commons.lang3.StringUtils.split(cmd, Constants.CMD_SEPARATOR);
            if (cmdArr.length == 1) {
                namespace = Constants.DEFAULT_NAMESPACE;
            } else {
                namespace = cmdArr[0];
            }
        }
        return namespace;
    }
}
